﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Protocol;
using server;

namespace SuperSocket.QuickStart.TelnetServer_AppServer
{
    public class TelnetSession : AppSession<TelnetSession>
    {
        Maticsoft.Model.RoleInfo mUserInfo = new Maticsoft.Model.RoleInfo();
        Maticsoft.DAL.RoleInfo mUserAction = new Maticsoft.DAL.RoleInfo();

        private Dictionary<string, Maticsoft.Model.Skill> skills = new Dictionary<string, Maticsoft.Model.Skill>();

        object muserObject = new object();

        int combat_id;

        public int Combat_id
        {
            get { return combat_id; }
            set { combat_id = value; }
        }

        int combat_side;

        public int Combat_side
        {
            get { return combat_side; }
            set { combat_side = value; }
        }

        combat_userinfo mcombat_userinfo;

        public combat_userinfo Mcombat_userinfo
        {
            get { return mcombat_userinfo; }
            set { mcombat_userinfo = value; }
        }
        

        public Dictionary<string, Maticsoft.Model.Skill> Skills
        {
            get { return skills; }
            set { skills = value; }
        }

        private Dictionary<string, baseskill> baseskills = new Dictionary<string, baseskill>();

        internal Dictionary<string, baseskill> Baseskills
        {
            get { return baseskills; }
            set { baseskills = value; }
        }

        const int POINT2HP = 20;
        const int POINT2MP = 10;
        const int POINT2AT = 4;
        const int POINT2DE = 2;


        protected override void OnSessionStarted()
        {
            //this.Send("Welcome to SuperSocket Telnet Server");
            baseskills = AppServer.Baseskills;
            skills = AppServer.Skills;
            mCombat_action = new combat_action();
            mcombat_userinfo = new combat_userinfo();
        }

        protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
        {
            //this.Send("Unknow request");
        }

        protected override void HandleException(Exception e)
        {
            //this.Send("Application error: {0}", e.Message);
        }

        protected override void OnSessionClosed(CloseReason reason)
        {
            base.OnSessionClosed(reason);
        }

        public new TelnetServer AppServer
        {
            get { return (TelnetServer)base.AppServer; }
        }

        public bool OnQuit(string cmd)
        {
            quitUser();
            return true;
        }

        public bool OnFirstLogin(string cmd)
        {
            protocolchange pc = new protocolchange();
            Dictionary<string, string> paras = pc.cmd2paras(cmd);
            //昵称，性别，baseskill
            this.mUserInfo.nickName = paras["nickname"];
            this.mUserInfo.baseskill = paras["baseskill"];
            this.mUserInfo.sex = paras["sex"];
            this.mUserInfo.IsFirst = 1;
            if (this.mUserAction.Update(this.mUserInfo))
            {
                sendCmd("c03&f=0");
            }
            else
            {
                sendCmd("c03&f=1");
            }              
            return true;
        }

        combat_action mCombat_action;

        public bool OnBattleAction(string cmd)
        {
            protocolchange pc = new protocolchange();
            Dictionary<string, string> paras = pc.cmd2paras(cmd);

            lock (muserObject)
            {

                if (paras["attack"] == "")
                {
                    Random ra = new Random();
                    int attack_random = ra.Next(1, 3);
                    if (attack_random == 1)
                    {
                        paras["attack"] = "1";
                    }
                    else if (attack_random == 2)
                    {
                        paras["attack"] = "2";
                    }
                    else
                    {
                        paras["attack"] = "3";
                    }


                    mCombat_action.attack = paras["attack"];
                }
                else
                {
                    mCombat_action.attack = paras["attack"];
                }

                if (paras["defence"] == "")
                {
                    Random ra = new Random();
                    int attack_random = ra.Next(1, 3);
                    if (attack_random == 1)
                    {
                        paras["defence"] = "1";
                    }
                    else if (attack_random == 2)
                    {
                        paras["defence"] = "2";
                    }
                    else
                    {
                        paras["defence"] = "3";
                    }


                    mCombat_action.attack = paras["attack"];
                }
                else
                {
                    mCombat_action.defence = paras["defence"];
                }


                mCombat_action.time = DateTime.Now;
                if (paras["skill"] == "")
                {
                    paras["skill"] = "基础攻击";
                    mCombat_action.skill = this.skills[paras["skill"]];
                }
                else
                {
                    mCombat_action.skill = this.skills[paras["skill"]];
                }
            }

            return true;
        }

        public void BattleVictory()
        {
            String cmd = "c0f&f=0";
            sendCmd(cmd);

            this.mUserInfo.totalVictory++;
            this.mUserInfo.NowVictory++;
            if (Convert.ToDateTime(this.mUserInfo.setupDate) > DateTime.Now)
            {
                if (this.mUserInfo.NowVictory >= 3)
                {
                    this.mUserInfo.sypoint++;
                    this.mUserInfo.NowVictory = 0;
                    this.mUserInfo.NowFailed = 0;
                }
            }
            else
            {
                if (this.mUserInfo.NowVictory >= 6)
                {
                    this.mUserInfo.sypoint++;
                    this.mUserInfo.NowVictory = 0;
                    this.mUserInfo.NowFailed = 0;
                }
            }

            this.mUserAction.Update(this.mUserInfo);

            return;
        }
        public void BattleFailed()
        {
            String cmd = "c0f&f=1";
            sendCmd(cmd);

            this.mUserInfo.totalFailed++;
            this.mUserInfo.NowFailed++;

            if (Convert.ToDateTime(this.mUserInfo.setupDate) > DateTime.Now)
            {
                if (this.mUserInfo.NowFailed >= 6)
                {
                    this.mUserInfo.sypoint++;
                    this.mUserInfo.NowVictory = 0;
                    this.mUserInfo.NowFailed = 0;
                }
            }
            else
            {
                if (this.mUserInfo.NowFailed >= 12)
                {
                    this.mUserInfo.sypoint++;
                    this.mUserInfo.NowVictory = 0;
                    this.mUserInfo.NowFailed = 0;
                }
            }
            this.mUserAction.Update(this.mUserInfo);

            return;
        }

        public void AfterBattle(TelnetSession enemy)
        {
            if (mCombat_action.skill == null)
            {
                return;
            }
            enemy.Mcombat_userinfo.St = enemy.Mcombat_userinfo.St - this.mCombat_action.skill.curse_at;
            enemy.Mcombat_userinfo.De = enemy.Mcombat_userinfo.De - this.mCombat_action.skill.curse_de;
            enemy.Mcombat_userinfo.Damage_hot = enemy.Mcombat_userinfo.Damage_hot - this.mCombat_action.skill.damage_hot;

            this.Mcombat_userinfo.Mp = this.Mcombat_userinfo.Mp - this.mCombat_action.skill.mp + this.mCombat_action.skill.mp_suck;
            this.Mcombat_userinfo.Hp = this.Mcombat_userinfo.Hp + this.mCombat_action.skill.hp_suck;
                        
        }

        String myBattleInfo;
        String enemyBattleInfo;

        public void BattleInfo(TelnetSession enemy)
        {
            String cmd;
            cmd = "c0c&f="+myBattleInfo;
            sendCmd(cmd);

            cmd = "c0c&f=" + enemyBattleInfo;
            enemy.sendCmd(cmd);
            return;
        }

        public void Battle(TelnetSession enemy)
        {
            int damage_number = 0;
            myBattleInfo = "";
            enemyBattleInfo = "";
            String part = null;
            int d_damage = 0;
            if (this.mCombat_action.attack!=enemy.mCombat_action.defence)
            {
                if (this.mCombat_action.attack == "1")
                {
                    enemy.Mcombat_userinfo.Head_number++;
                    damage_number = enemy.Mcombat_userinfo.Head_number;
                    part = "头部";
                }

                if (this.mCombat_action.attack == "2")
                {
                    enemy.Mcombat_userinfo.Chest_number++;
                    damage_number = enemy.Mcombat_userinfo.Chest_number;
                    part = "胸部";
                }

                if (this.mCombat_action.attack == "3")
                {
                    enemy.Mcombat_userinfo.Lag_number++;
                    damage_number = enemy.Mcombat_userinfo.Lag_number;
                    part = "腿部";
                }

                d_damage = (int)((this.mCombat_action.skill.damage + this.mcombat_userinfo.St) * (1 + this.mcombat_userinfo.St / 200)
                            / (1 + enemy.Mcombat_userinfo.De / 200) * (1 + damage_number * 0.1));

                enemy.Mcombat_userinfo.Hp = (int)((Double)enemy.Mcombat_userinfo.Hp -d_damage);

                enemy.Mcombat_userinfo.Hp = enemy.Mcombat_userinfo.Hp - enemy.Mcombat_userinfo.Damage_hot;

                enemy.Mcombat_userinfo.Mp = enemy.Mcombat_userinfo.Mp - this.mCombat_action.skill.mp;

                myBattleInfo = myBattleInfo + "你使用" + this.mCombat_action.skill.name + "打中了对方的"+ part + ";";
                myBattleInfo = myBattleInfo + "对方受到" + d_damage.ToString() + "点伤害;";
                if (enemy.Mcombat_userinfo.Damage_hot>0)
                {
                    myBattleInfo = myBattleInfo + "对方受到流血" + d_damage.ToString() + "点伤害;";
                }


                enemyBattleInfo = enemyBattleInfo + "对方使用" + this.mCombat_action.skill.name + "打中了你的" + part + ";";
                enemyBattleInfo = enemyBattleInfo + "你受到" + d_damage.ToString() + "点伤害;";
                if (enemy.Mcombat_userinfo.Damage_hot > 0)
                {
                    enemyBattleInfo = enemyBattleInfo + "你受到流血" + d_damage.ToString() + "点伤害;";
                }
            } 
            else
            {
                myBattleInfo = myBattleInfo + "你的攻击被敌人格挡;";
                enemyBattleInfo = enemyBattleInfo + "你的成功格挡住敌人的攻击;";
            }
            
        }


        public bool OnBattleQuit(string cmd)
        {
            bool ret = AppServer.MAllcombat.quit(this);
            if (ret == true)
            {
                sendCmd("c09&f=0");
            }
            else
            {
                sendCmd("c09&f=1");
            }
            return true;
        }

        public bool OnBattleJoin(string cmd)
        {
            bool ret = AppServer.MAllcombat.join(this);
            if (ret == true)
            {
                sendCmd("c08&f=0");
                mcombat_userinfo.Baseskill = mUserInfo.baseskill;
                mcombat_userinfo.De = mUserInfo.de;
                mcombat_userinfo.Hp = mUserInfo.hp;
                mcombat_userinfo.Mp = mUserInfo.mp;
                mcombat_userinfo.Nickname = mUserInfo.nickName;
                mcombat_userinfo.Sex = mUserInfo.sex;
                mcombat_userinfo.Skills = mUserInfo.skills;
                mcombat_userinfo.St = mUserInfo.st;
                mcombat_userinfo.Totalfailed = mUserInfo.totalFailed;
                mcombat_userinfo.Totalvictory = mUserInfo.totalVictory;
            }
            else
            {
                sendCmd("c08&f=1");
            }
            return true;
        }
        public void BattleStart()
        {
            sendCmd("c0e&f=0");
        }
        public void BattleEnd()
        {
            sendCmd("c0f&f=0");
        }

        public bool OnUsePoint(string cmd)
        {
            int addhp = 0;
            int addmp = 0;
            int addat = 0;
            int addde = 0;
            string skillName = "";
            bool validCmd = true;

            protocolchange pc = new protocolchange();
            Dictionary<string, string> paras = pc.cmd2paras(cmd);

            Maticsoft.Model.Skill learnSkill = new Maticsoft.Model.Skill();
            if (paras.ContainsKey("addhp"))
            {
                addhp = int.Parse(paras["addhp"]);
            }
            if (paras.ContainsKey("addmp"))
            {
                addmp = int.Parse(paras["addmp"]);
            }
            if (paras.ContainsKey("addat"))
            {
                addat = int.Parse(paras["addat"]);
            }
            if (paras.ContainsKey("addde"))
            {
                addde = int.Parse(paras["addde"]);
            }
            if (paras.ContainsKey("skillName"))
            {
                skillName = paras["skillName"];
                if (skills.ContainsKey(skillName))
                {
                    learnSkill = skills[skillName];
                }
                else
                {
                    validCmd = false;
                }
            }


            if (mUserInfo.sypoint < (addde + addhp + addmp + addat + learnSkill.needPoint))
            {
                validCmd = false;
            }
            else
            {
                this.mUserInfo.hp = this.mUserInfo.hp + addhp * POINT2HP;
                this.mUserInfo.mp = this.mUserInfo.mp + addmp * POINT2MP;
                this.mUserInfo.de = this.mUserInfo.de + addde * POINT2AT;
                this.mUserInfo.st = this.mUserInfo.st + addat * POINT2AT;
                if (validCmd ==true)
                {
                    if (this.mUserInfo.skills == "")
                    {
                        this.mUserInfo.skills = learnSkill.name;
                    }
                    else
                    {
                        this.mUserInfo.skills = this.mUserInfo.skills + "*" + learnSkill.name;
                    }
                }

                this.mUserInfo.sypoint = this.mUserInfo.sypoint - addhp - addmp - addde - addat - learnSkill.needPoint;

                this.mUserAction.Update(this.mUserInfo);

                sendCmd("c07&f=0");
            }

            if (validCmd == false)
            {
                sendCmd("c07&f=1");
            }
            return true;
        }

        public bool OnGetBaseSkill(string cmd)
        {
            //获得baseSkill
            string skillcmd;
            int number = 0;
            foreach (baseskill abaseSkill in baseskills.Values)
            {
                skillcmd = "c05";
                skillcmd = skillcmd + "&total=" + baseskills.Count;
                number++;
                skillcmd = skillcmd + "&number=" + number.ToString();
                skillcmd = skillcmd + "&name=" + abaseSkill.getName();
                skillcmd = skillcmd + "&desc=" + abaseSkill.getDesc();
                sendCmd(skillcmd);
            }
            return true;
        }

        public bool OnGetAllSkills(string cmd)
        {
            //获得AllSkills
            string skillcmd;
            int number = 0;
            foreach (Maticsoft.Model.Skill aSkill in skills.Values)
            {
                skillcmd = "c04";
                skillcmd = skillcmd + "&total=" + skills.Count;
                number++;
                skillcmd = skillcmd + "&number=" + number.ToString();
                skillcmd = skillcmd + "&name=" + aSkill.name;
                skillcmd = skillcmd + "&curse_at=" + aSkill.curse_at;
                skillcmd = skillcmd + "&curse_de=" + aSkill.curse_de;
                skillcmd = skillcmd + "&damage=" + aSkill.damage;
                skillcmd = skillcmd + "&damage_hot=" + aSkill.damage_hot;
                skillcmd = skillcmd + "&damage_hot_time=" + aSkill.damage_hot_time;
                skillcmd = skillcmd + "&damage_poison=" + aSkill.damage_poison;
                skillcmd = skillcmd + "&desc=" + aSkill.desc;
                skillcmd = skillcmd + "&hp_suck=" + aSkill.hp_suck;
                skillcmd = skillcmd + "&mp=" + aSkill.mp;
                skillcmd = skillcmd + "&mp_suck=" + aSkill.mp_suck;
                sendCmd(skillcmd);
            }
            return true;
        }

        public bool OnGetRoleinfo(string cmd)
        {
            string roleInfocmd;
            roleInfocmd = "c06";
            roleInfocmd = roleInfocmd + "&name=" + this.mUserInfo.name;
            roleInfocmd = roleInfocmd + "&nickName=" + this.mUserInfo.nickName;
            roleInfocmd = roleInfocmd + "&baseskill=" + this.mUserInfo.baseskill;
            roleInfocmd = roleInfocmd + "&de=" + this.mUserInfo.de;
            roleInfocmd = roleInfocmd + "&hp=" + this.mUserInfo.hp;
            roleInfocmd = roleInfocmd + "&IsFirst=" + this.mUserInfo.IsFirst;
            roleInfocmd = roleInfocmd + "&mp=" + this.mUserInfo.mp;
            roleInfocmd = roleInfocmd + "&NowFailed=" + this.mUserInfo.NowFailed;
            roleInfocmd = roleInfocmd + "&NowVictory=" + this.mUserInfo.NowVictory;
            roleInfocmd = roleInfocmd + "&sex=" + this.mUserInfo.sex;
            roleInfocmd = roleInfocmd + "&skills=" + this.mUserInfo.skills;
            roleInfocmd = roleInfocmd + "&st=" + this.mUserInfo.st;
            roleInfocmd = roleInfocmd + "&sypoint=" + this.mUserInfo.sypoint;
            roleInfocmd = roleInfocmd + "&totalFailed=" + this.mUserInfo.totalFailed;
            roleInfocmd = roleInfocmd + "&totalpoint=" + this.mUserInfo.totalpoint;
            roleInfocmd = roleInfocmd + "&totalVictory=" + this.mUserInfo.totalVictory;
            sendCmd(roleInfocmd);
            return true;
        }


        public String GetRoleinfo()
        {
            string roleInfocmd;
            roleInfocmd = "";
            roleInfocmd = roleInfocmd + "&name=" + this.mUserInfo.name;
            roleInfocmd = roleInfocmd + "&nickName=" + this.mUserInfo.nickName;
            roleInfocmd = roleInfocmd + "&baseskill=" + this.mUserInfo.baseskill;
            roleInfocmd = roleInfocmd + "&de=" + this.mUserInfo.de;
            roleInfocmd = roleInfocmd + "&hp=" + this.mUserInfo.hp;
            roleInfocmd = roleInfocmd + "&IsFirst=" + this.mUserInfo.IsFirst;
            roleInfocmd = roleInfocmd + "&mp=" + this.mUserInfo.mp;
            roleInfocmd = roleInfocmd + "&NowFailed=" + this.mUserInfo.NowFailed;
            roleInfocmd = roleInfocmd + "&NowVictory=" + this.mUserInfo.NowVictory;
            roleInfocmd = roleInfocmd + "&sex=" + this.mUserInfo.sex;
            roleInfocmd = roleInfocmd + "&skills=" + this.mUserInfo.skills;
            roleInfocmd = roleInfocmd + "&st=" + this.mUserInfo.st;
            roleInfocmd = roleInfocmd + "&sypoint=" + this.mUserInfo.sypoint;
            roleInfocmd = roleInfocmd + "&totalFailed=" + this.mUserInfo.totalFailed;
            roleInfocmd = roleInfocmd + "&totalpoint=" + this.mUserInfo.totalpoint;
            roleInfocmd = roleInfocmd + "&totalVictory=" + this.mUserInfo.totalVictory;
            return roleInfocmd;
        }

         public String Getcombat_userinfo()
        {
            String roleInfocmd;
            roleInfocmd = "c0a";
            roleInfocmd = roleInfocmd + "&Baseskill=" + this.mcombat_userinfo.Baseskill;
            roleInfocmd = roleInfocmd + "&De=" + this.mcombat_userinfo.De;
            roleInfocmd = roleInfocmd + "&Hp=" + this.mcombat_userinfo.Hp;
            roleInfocmd = roleInfocmd + "&Mp=" + this.mcombat_userinfo.Mp;
            roleInfocmd = roleInfocmd + "&Nickname=" + this.mcombat_userinfo.Nickname;
            roleInfocmd = roleInfocmd + "&Sex=" + this.mcombat_userinfo.Sex;
            roleInfocmd = roleInfocmd + "&Skills=" + this.mcombat_userinfo.Skills;
            roleInfocmd = roleInfocmd + "&St=" + this.mcombat_userinfo.St;
            roleInfocmd = roleInfocmd + "&Totalfailed=" + this.mcombat_userinfo.Totalfailed;
            roleInfocmd = roleInfocmd + "&Totalvictory=" + this.mcombat_userinfo.Totalvictory;
            return roleInfocmd;
        }
        public void Sendcombat_userinfo()
         {
             String roleInfocmd;
             roleInfocmd = "c0b";
             roleInfocmd = roleInfocmd + "&Baseskill=" + this.mcombat_userinfo.Baseskill;
             roleInfocmd = roleInfocmd + "&De=" + this.mcombat_userinfo.De;
             roleInfocmd = roleInfocmd + "&Hp=" + this.mcombat_userinfo.Hp;
             roleInfocmd = roleInfocmd + "&Mp=" + this.mcombat_userinfo.Mp;
             roleInfocmd = roleInfocmd + "&Nickname=" + this.mcombat_userinfo.Nickname;
             roleInfocmd = roleInfocmd + "&Sex=" + this.mcombat_userinfo.Sex;
             roleInfocmd = roleInfocmd + "&Skills=" + this.mcombat_userinfo.Skills;
             roleInfocmd = roleInfocmd + "&St=" + this.mcombat_userinfo.St;
             roleInfocmd = roleInfocmd + "&Totalfailed=" + this.mcombat_userinfo.Totalfailed;
             roleInfocmd = roleInfocmd + "&Totalvictory=" + this.mcombat_userinfo.Totalvictory;
             sendCmd(roleInfocmd);
         }



        public bool OnLogin(string cmd)
        {
            protocolchange pc = new protocolchange();
            Dictionary<string, string> paras = pc.cmd2paras(cmd);

            if (verifyUser(paras["name"], paras["password"]) == true)
            {
                //updateUser(this.mUserInfo.name, this, 0);
                sendCmd("c01&f=0");
            }
            else
            {
                sendCmd("c01&f=1");
                //quitUser();
            }

            return true;
        }

        public int OnRegister(string cmd)
        {
            protocolchange pc = new protocolchange();
            Dictionary<string, string> paras = pc.cmd2paras(cmd);

            if (registerUser(paras["name"], paras["password"]) == true)
            {
                //成功
                sendCmd("c02&f=0");
                //quitUser();
            }
            else
            {
                //失败
                sendCmd("c02&f=1");
                //quitUser();
            }   

            return 0;
        }

        bool registerUser(String name, String password)
        {
            bool ret;
            ret = this.mUserAction.Exists(name);
            if (ret == true)
            {
                return false;
            }

            this.mUserInfo.name = name;
            this.mUserInfo.password = password;
            this.mUserInfo.sex = "";
            this.mUserInfo.qq = "";
            this.mUserInfo.setupDate = DateTime.Now.ToString();
            this.mUserInfo.NowFailed = 0;
            this.mUserInfo.NowVictory = 0;
            this.mUserInfo.hp = 5*POINT2HP;
            this.mUserInfo.mp = 5*POINT2MP;
            this.mUserInfo.st = 5*POINT2AT;
            this.mUserInfo.de = 5*POINT2DE;
            this.mUserInfo.totalFailed = 0;
            this.mUserInfo.totalpoint = 30;
            this.mUserInfo.totalVictory = 0;
            this.mUserInfo.sypoint = 10;
            this.mUserInfo.baseskill = "";
            this.mUserInfo.IsFirst = 0;
            this.mUserInfo.isPaidUser = 0;
            this.mUserInfo.nickName = "";

            ret = this.mUserAction.Add(this.mUserInfo);

            return ret;
            //return msqlclient.regUser(name, password, sex, qq);
        }

        bool verifyUser(String name, String password)
        {

            this.mUserInfo = this.mUserAction.GetModel(name);
            if (this.mUserInfo == null)
            {
                return false;
            }
            else
            {
                if (password != this.mUserInfo.password)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }
        public void sendCmd(String cmd)
        {
            lock (muserObject)
            {
                cmd = cmd + "\r\n";
                this.Send(cmd);
            }
            return;
        }
        public void quitUser()
        {
            this.Close(CloseReason.ClientClosing);
        }
    }
    
}
